/*
 * @Description: 缓存 redis 连接
 * @Version: 1.0
 * @Autor: JiaJun Wu
 * @Date: 2021-09-06 16:02:07
 * @LastEditors: JiaJun Wu
 * @LastEditTime: 2021-09-18 15:15:35
 */
extern crate r2d2;
extern crate r2d2_redis;
use super::toml_conf::SETTING;
use r2d2::PooledConnection;
use r2d2_redis::RedisConnectionManager;
use rocket::http::Status;
use rocket::request::{FromRequest, Outcome};
use rocket::Request;
use std::ops::{Deref, DerefMut};

type Pool = r2d2::Pool<RedisConnectionManager>;
pub struct Connection(pub PooledConnection<RedisConnectionManager>);

pub type RedisConn = Connection;

/// 初始化缓存连接
#[allow(dead_code)]
pub fn init_pool() -> Pool {
    let manager = RedisConnectionManager::new(SETTING.caches.redis.as_str());
    let manager = match manager {
        Ok(db) => db,
        Err(e) => panic!("错误：连接redis失败 {}", e),
    };

    match Pool::builder().max_size(2).build(manager) {
        Ok(pool) => pool,
        Err(e) => panic!("错误：连接redis失败 {}", e),
    }
}

/// 创建FromRequest的实现，以便可以在每个api端点上提供Conn
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Connection {
    type Error = ();

    async fn from_request(request: &'r Request<'_>) -> Outcome<Connection, ()> {
        let pool = request.rocket().state::<Pool>().unwrap();
        match pool.get() {
            Ok(db) => Outcome::Success(Connection(db)),
            Err(_) => Outcome::Failure((Status::ServiceUnavailable, ())),
        }
    }
}

/// 取消引用Conn时，返回mongo连接。
impl Deref for Connection {
    type Target = PooledConnection<RedisConnectionManager>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for Connection {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}
